package com.sgidi.einvoice.service;

import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.canvas.parser.PdfTextExtractor;
import com.itextpdf.kernel.pdf.canvas.parser.listener.LocationTextExtractionStrategy;
import com.itextpdf.kernel.pdf.canvas.parser.listener.SimpleTextExtractionStrategy;
import com.itextpdf.kernel.pdf.canvas.parser.listener.TextChunk;

import org.apache.commons.codec.binary.Base64;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.text.PDFTextStripper;
//import com.snowtide.PDF;
//import com.snowtide.pdf.Document;
//import com.snowtide.pdf.OutputTarget;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.math.BigDecimal;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 专用于处理电子发票识别的类
 *
 * @author arthurlee
 */

public class PdfInvoiceExtractor {

    private static String getBase64Image(PDDocument doc) throws IOException {
        PDFRenderer renderer = new PDFRenderer(doc);
        BufferedImage image = renderer.renderImageWithDPI(0, 150);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ImageIO.write(image, "png", byteArrayOutputStream);
        return "data:image/png;base64," + new String(Base64.encodeBase64(byteArrayOutputStream.toByteArray()));
    }

    static private String getPdfFirstPageText(PDDocument doc) throws IOException {
        PDFTextStripper textStripper = new PDFTextStripper();
        textStripper.setStartPage(1);
        textStripper.setEndPage(1);
        textStripper.setSortByPosition(true);
        String fullText = textStripper.getText(doc);
        return replace(fullText).replaceAll("（", "(").replaceAll("）", ")").replaceAll("￥", "¥");
    }

    static private String getPdfFirstPageTextv1(String path) throws IOException {

        // 1. 打开PDF文件
        PdfReader pdfReader = new PdfReader(path);
        PdfDocument pdfDocument = new PdfDocument(pdfReader);

        // 2. 获取页面数量
        int numberOfPages = pdfDocument.getNumberOfPages();

        // 3. 提取文本
        StringBuilder text = new StringBuilder();
        for (int page = 1; page <= numberOfPages; page++) {
            PdfPage pdfPage = pdfDocument.getPage(page);

            // 创建文本提取策略
            SimpleTextExtractionStrategy strategy = new SimpleTextExtractionStrategy();

            // 提取文本
            PdfTextExtractor.getTextFromPage(pdfPage, strategy);

            // 获取提取的文本
            String pageText = strategy.getResultantText();
            text.append(pageText);
        }

        // 4. 关闭PDF文件
        pdfDocument.close();
        // 5. 输出提取的文本
        return replace(text.toString()).replaceAll("（", "(").replaceAll("）", ")").replaceAll("￥", "¥");


    }



    public static Invoice extract(File file) throws IOException {
        Invoice invoice = new Invoice();
        PDDocument doc = PDDocument.load(file);
        invoice.setBase64Png(getBase64Image(doc));
        String allText = getPdfFirstPageText(doc);
        String allText1 = getPdfFirstPageTextv1(file.getAbsolutePath());
        System.out.println(allText);
        if (!allText.contains("发票")) {
            throw new InvalidObjectException("不是发票文件");
        }
        // Important 新版发票没有代码，所以使用这个魔法字符来判断是不是新版发票
        boolean isNewInvoice = !allText.contains("代码:");
        {
            // NOTE 这里依赖的模式是发票代码和发票号码的文字需要出现在一行
            String reg = "代码:(?<code>\\d{12})|(号码:)\\D*(?<number>\\d+\\D*\\d*)";
            Pattern pattern = Pattern.compile(reg);
            Matcher matcher = pattern.matcher(allText);
            while (matcher.find()) {
                if (matcher.group("code") != null) {
                    invoice.setCode(matcher.group("code"));
                } else if (matcher.group("number") != null) {
                    try{
                        String number = matcher.group("number");
                        number = number.replaceAll("\\D", "").substring(0, isNewInvoice ? 20 : 8);
                        invoice.setNumber(number);
                    } catch (Exception e) {
                        String reg1 = "\\d{20}"; // 正确的正则表达式
                        Pattern pattern1 = Pattern.compile(reg1);
                        Matcher matcher1 = pattern1.matcher(allText1);

                        if (matcher1.find()) { // 进行匹配操作
                            String number = matcher1.group(); // 使用 group() 方法获取整个匹配结果
                            invoice.setNumber(number);
                        } else {
                            // 如果没有找到匹配的结果，可以进行相应的处理
                        }
                    }

                }
            }
        }
        { // 匹配日期
            String reg = "(?<date>\\d{4}年\\d{2}月\\d{2}日)";
            Pattern pattern = Pattern.compile(reg);
            Matcher matcher = pattern.matcher(allText);
            if (matcher.find()) {
                try {
                    invoice.setDate(matcher.group("date"));
                } catch (Exception ignored) {
                }
            }
        }
        {
            String reg = "小写\\D*(?<amount>\\d*\\.\\d\\d)";
            Pattern pattern = Pattern.compile(reg);
            Matcher matcher = pattern.matcher(allText);
            if (matcher.find()) {
                try {
                    invoice.setTotalAmount(new BigDecimal(matcher.group("amount")));
                } catch (Exception e) {
                    invoice.setTotalAmount(new BigDecimal(0));
                }
            }
        }
        {
            //匹配发票抬头
            String reg = "电子发票[(].+[)]";
            Pattern pattern = Pattern.compile(reg);
            Matcher matcher = pattern.matcher(allText1);
            if (matcher.find()) {
                try {
                    invoice.setTitle(matcher.group(0));

                } catch (Exception e) {

                    invoice.setTotalAmount(new BigDecimal(0));
                }
            }
            else {
                String reg1="(北京|天津|河北|山西|内蒙古|辽宁|吉林|黑龙江|上海|江苏|浙江|安徽|福建|江西|山东|河南|湖北|湖南|广东|广西|海南|重庆|四川|贵州|云南|西藏|陕西|甘肃|青海|宁夏|新疆|台湾|香港|澳门)增值税";
                Pattern pattern1 = Pattern.compile(reg1);
                Matcher matcher1 = pattern1.matcher(allText);
                if (matcher1.find()) {
                    try {
                        invoice.setTitle(matcher.group(0));
                    } catch (Exception e) {
                        //System.out.println("其它发票");
                    }
                }

            }
        }
        doc.close();
        return invoice;
    }

    private static String replace(String str) {
        return str.replaceAll(" ", "").replaceAll("　", "").replaceAll("：", ":").replaceAll(" ", "");
    }
}